package cn.qinhao.pethome.system.service.impl;

import cn.qinhao.pethome.annotation.PreAuthorize;
import cn.qinhao.pethome.basic.base.service.impl.BaseServiceImpl;
import cn.qinhao.pethome.basic.until.Classutil;
import cn.qinhao.pethome.system.domain.Permission;
import cn.qinhao.pethome.system.mapper.PermissionMapper;
import cn.qinhao.pethome.system.service.IPermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author qinhao
 * @since 2023-03-04
 */
@Service
public class PermissionServiceImpl extends BaseServiceImpl<Permission> implements IPermissionService {
    /**
     *    第一步: 找到对应的class文件 --通过类加载器去获取根节点
     *    第二步: 找到对应的包(路径全是死的)
     *    第三步: 找到对应的子集包 并且必须包含controller文件夹
     *    第四步: 找到包里面对应的类   这个类必须是以controller结尾的
     *    第五步: 通过反射得到里面所有方法的注解(我们只要我们自己定义的注解)
     *    第六步: 解析自定义注解  name value
     *           去判断sn是否存在 如果存在就跳过不保存
     *    第七步: 将数据保存到数据库就可以了
     */
    @Autowired
    private PermissionMapper permissionMapper;
    private static final String  PKG_PREFIX   = "cn.qinhao.pethome.";//前缀，注意一定不要忘记 点
    private static final String  PKG_SUFFIX   = ".controller";
    @Override
    public void init() {
        try {//path是获取得classes这个根路径+三层路径得固定路径
            String path = this.getClass().getResource("/").getPath()+"cn/qinhao/pethome";
            File file = new File(path);//这里是文件夹
            File[] files = file.listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    return file.isDirectory(); //是文件夹才保存到files集合里面  不要文件
                }
            });

            //获取org.yaosang.*.web.controller里面所有的类
            Set<Class> clazzes = new HashSet<>();//存放完整路径下  找到的controller的classes文件
            for (File fileTmp : files) {
                System.out.println(fileTmp.getName());//pethome下面的所有文件，加上前缀和后缀就是完整的路径
                //专门用来读取class文件的
                clazzes.addAll(Classutil.getClasses(PKG_PREFIX+fileTmp.getName()+PKG_SUFFIX));
            }

            //循环找到的classes集合  重点
            for (Class clazz : clazzes) {
                Method[] methods = clazz.getMethods();//获取所有方法
                if(methods == null){//没有方法就没必要执行
                    continue;  //跳过本次循环  break;结束循环
                }
                for (Method method : methods) {//循环方法
                        String url = getUrl(clazz, method);//根据工具类获取地址（该方法会扫描类+方法上面的路径）
                    // 获取method方法上的PreAuthorize自定义注解
                    PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
                    if(annotation == null){
                        continue;  //跳过本次循环
                    }
                    //在我们的Permission中  sn是唯一的不可以重复
                    Permission isNull = permissionMapper.loadBySn(annotation.value());
                    if(isNull != null){//不为空再添加就重复了
                        continue;
                    }//为空再保存
                    Permission permission = new Permission();
                    permission.setName(annotation.name());
                    permission.setSn(annotation.value());
                    permission.setUrl(url);
                    this.add(permission);//保存数据库
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
//获取路径的until
    private String getUrl(Class clazz, Method method) {
        String classPath = "";
        Annotation annotation = clazz.getAnnotation(RequestMapping.class);
        if (annotation!=null){
            RequestMapping requestMapping = (RequestMapping) annotation;
            String[] values = requestMapping.value();
            if(values!=null&&values.length>0){
                classPath = values[0];
                if (!"".equals(classPath)&&!classPath.startsWith("/"))
                    classPath="/"+classPath;
            }
        }
        GetMapping getMapping =  method.getAnnotation(GetMapping.class);
        String methodPath = "";
        if (getMapping!=null){
            String[] values = getMapping.value();
            if(values!=null&&values.length>0){
                methodPath = values[0];
                if (!"".equals(methodPath)&&!methodPath.startsWith("/"))
                    methodPath="/"+methodPath;
            }
        }
        PostMapping postMapping =  method.getAnnotation(PostMapping.class);
        if (postMapping!=null){
            String[] values = postMapping.value();
            if(values!=null&&values.length>0){
                methodPath = values[0];
                if (!"".equals(methodPath)&&!methodPath.startsWith("/"))
                    methodPath="/"+methodPath;
            }
        }
        DeleteMapping deleteMapping =  method.getAnnotation(DeleteMapping.class);
        if (deleteMapping!=null){
            String[] values = deleteMapping.value();
            if(values!=null&&values.length>0){
                methodPath = values[0];
                if (!"".equals(methodPath)&&!methodPath.startsWith("/"))
                    methodPath="/"+methodPath;
            }
        }
        PutMapping putMapping =  method.getAnnotation(PutMapping.class);
        if (putMapping!=null){
            String[] values = putMapping.value();
            if(values!=null&&values.length>0){
                methodPath = values[0];
                if (!"".equals(methodPath)&&!methodPath.startsWith("/"))
                    methodPath="/"+methodPath;
            }

        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping!=null){
            String[] values = patchMapping.value();
            if(values!=null&&values.length>0){
                methodPath = values[0];
                if (!"".equals(methodPath)&&!methodPath.startsWith("/"))
                    methodPath="/"+methodPath;
            }
        }
        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        if (requestMapping!=null){
            String[] values = requestMapping.value();
            if(values!=null&&values.length>0){
                methodPath = values[0];
                if (!"".equals(methodPath)&&!methodPath.startsWith("/"))
                    methodPath="/"+methodPath;
            }
        }
        return classPath+methodPath;
    }

}

